import java.util.Date;
import java.util.concurrent.TimeUnit;

import jobs.SynchronizationJob;

import models.Company;
import models.Role;
import models.User;
import play.Application;
import play.GlobalSettings;
import play.libs.Akka;
import play.mvc.Call;
import scala.concurrent.duration.Duration;
import scala.concurrent.duration.FiniteDuration;
import security.ConsoleUsernamePasswordAuthProvider.ConsoleSignup;
import security.ConsoleUsernamePasswordAuthUser;

import com.feth.play.module.pa.PlayAuthenticate;
import com.feth.play.module.pa.PlayAuthenticate.Resolver;
import com.feth.play.module.pa.exceptions.AccessDeniedException;
import com.feth.play.module.pa.exceptions.AuthException;

import controllers.routes;

public class Global extends GlobalSettings {

	private static final String DEFAULT_PASSWORD = "zensconsole2013";
	private static final FiniteDuration SIXTY_SECONDS = Duration.create(60, TimeUnit.SECONDS);

	@Override
	public void onStart(Application app) {
		PlayAuthenticate.setResolver(new Resolver() {
			@Override
			public Call login() {
				return routes.Application.login();
			}

			@Override
			public Call afterAuth() {
				return routes.Application.index();
			}

			@Override
			public Call afterLogout() {
				return routes.Application.index();
			}

			@Override
			public Call auth(final String provider) {
				return com.feth.play.module.pa.controllers.routes.Authenticate.authenticate(provider);
			}

			@Override
			public Call askLink() {
				return null;
			}

			@Override
			public Call askMerge() {
				return null;
			}

			@Override
			public Call onException(AuthException e) {
				if (e instanceof AccessDeniedException) {
					AccessDeniedException exception = (AccessDeniedException) e;
					return routes.Application.authenticationDenied(exception.getProviderKey());
				}
				return super.onException(e);
			}
		});

		initializeData();

		startSynchronization();
	}

	/**
	 * Synchronization every 60 seconds.
	 */
	private void startSynchronization() {
		Akka.system().scheduler().schedule(Duration.Zero(), SIXTY_SECONDS, new Runnable() {
			public void run() {
				SynchronizationJob.sync();
			}
		}, Akka.system().dispatcher());
	}

	/**
	 * Initializes the data for the ZenS console application
	 */
	private void initializeData() {
		addRole(controllers.Application.ROLE_ADMIN);
		addRole(controllers.Application.ROLE_USER);

		Company company = addCompany("ZenS", "se");

		addUser(company, "junejava@gmail.com", "Jiraporn", "Yindeemoh Johansson");

		addUser(company, "garretist@gmail.com", "Mattias", "Johansson");

		addUser(company, "xuxuan@gmail.com", "Xuan", "Xu");

		addUser(company, "prashantdang@gmail.com", "Prashant", "Dang");
	}

	/**
	 * Add a role with a name
	 * 
	 * @param roleName
	 *            The role name
	 * @return The role
	 */
	private Role addRole(String roleName) {
		Role role = Role.findByRoleName(roleName);
		if (role == null) {
			role = new Role();
			role.setName(roleName);
			role.save();
		}
		return role;
	}

	/**
	 * Add a company with a name and country code
	 * 
	 * @param name
	 *            The name
	 * @param countryCode
	 *            The country code
	 * @return The company
	 */
	private Company addCompany(String name, String countryCode) {
		Company company = Company.find.where().eq("countryCode", countryCode).eq("name", name).findUnique();
		if (company == null) {
			company = new Company();
			company.setName(name);
			company.setCompanyId(countryCode.toLowerCase() + "-" + name.toLowerCase().replace(" ", ""));
			company.setCountryCode(countryCode);
			company.setCreatedDate(new Date());
			company.setLastModifiedDate(new Date());
			company.save();
		}
		return company;
	}

	/**
	 * Add user for default password (zensconsole2013)
	 * 
	 * @param company
	 *            The company
	 * @param email
	 *            The email address
	 * @param firstName
	 *            The first name
	 * @param lastName
	 *            The last name
	 */
	private void addUser(Company company, String email, String firstName, String lastName) {
		User user = User.findByEmail(email);
		if (user == null) {
			ConsoleSignup signup = new ConsoleSignup();
			signup.email = email;
			signup.password = DEFAULT_PASSWORD;
			signup.firstName = firstName;
			signup.lastName = lastName;
			user = User.create(new ConsoleUsernamePasswordAuthUser(signup));
			user.setCompany(company);
			user.setEmailValidated(true);
			user.addRole(Role.findByRoleName(controllers.Application.ROLE_ADMIN));
			user.save();
		}
	}
}
